/*
 * Proto Framework v.900
 * http://devblog.techhead.biz/2009/04/prototype-based-programming-in_04.html
 *
 * Copyright (c) 2009 Jonathan Hawkes
 * Licensed under the 'Do Whatever You Want With It' license.
 * Just please give credit where credit is due,
 * and post any noteworthy changes to the dev blog.
 */

/**
 * The prototype of all objects in this small
 * prototype framework.
 */
var biz$techhead$Proto = {

  __proto__: Object.prototype,

  /**
   * Clone this object and (optionally) invoke an initializer.
   * Should NOT be overriden.
   * Override 'onclone' instead.
   */
  clone: function(init) {
    var Clone = function(init) {
      this.__proto__ = Clone.prototype;
      this.constructor = Clone;
      this.onclone();
      if (init) {
        if (init instanceof Function)
          this.init(init);
        else
          this.assign(init);
      }
    }
    Clone.prototype = this;
    return new Clone(init);
  },
  
  /**
   * This event fires on the new child of this object
   * whenever 'clone' is called.
   * It is analagous to a constructor.
   */
  onclone: function() {},
  
  /**
   * Invokes an initializer function on this object.
   * It supplies this object's super prototype as the
   * first argument, and provides an optional second
   * argument to those initializers that declare
   * two or more parameters. The second argument is a
   * function that will install the initializer 'onclone'
   * when invoked.
   */
  init: function(init) {
    var _this = this,
        _super = this.__proto__;
    if (init.length > 1) {
      init.call(this, _super,
        function() {
          var hasonclone = _this.hasOwnProperty('onclone'),
              onclone = _this.onclone;
          _this.onclone = function() {
            var _this = this;
            var f = hasonclone ?
              function() { onclone.call(_this) } :
              function() { _super.onclone.call(_this) };
            init.call(this, _super, f);
          };
        });
    } else {
      init.call(this, _super);
    }
  },

  /**
   * Shallow copies the given properties onto this object.
   */
  assign: function(props) {
    for (var key in props) {
      var value = props[key];
      if (this[key] != value)
        this[key] = value;
    }
    return this;
  }
  
}
